package com.example.demo.service;

import com.example.demo.common.dto.ResData;
import com.example.demo.dao.BaseDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author Gavin
 * @date 2020.08.03 16:00
 */
@Service
public class UserService {
    @Autowired
    private BaseDao bd;
    @Autowired
    private ServiceB sb;

    /**
     * 演示spring事务的传播属性</br>
     * Propagation.REQUIRED:spring<strong>默认</strong>的传播属性,加入当前事务，出错都会回滚。如果没有事务就新起一个事务，出错只回滚该内部的方法，外部demoA不受影响
     * Propagation.SUPPORTS:如果当前在事务中，即以事务的形式运行，如果当前不再一个事务中，那么就以非事务的形式运行,非事务运行出错不会进行回滚
     * Propagation.MANDATORY:必须在一个事务中运行。也就是说，他只能被一个父事务调用。否则，他就要抛出异常
     * Propagation.REQUIRES_NEW:新启一个事务，两个事务隔离互相不影响
     * Propagation.NOT_SUPPORTED:当前不支持事务。如果demoA为required事务，则会先挂起该事务，然后以非事务的方式执行demoB
     * Propagation.REQUIRES_NEW:demoB新起一个事务，两个事务之间隔离互不影响
     * Propagation.NEVER:不能在事务中运行。加入demoA事务为REQUIRED，demoB为NEVER，那么就会抛错
     * Propagation.NESTED:理解Nested的关键是savepoint。他与REQUIRES_NEW的区别是，REQUIRES_NEW另起一个事务，将会与他的父事务相互独立,
     * 而Nested的事务和他的父事务是相依的，他的提交是要等和他的父事务一块提交的。也就是说，如果父事务最后回滚，他也要回滚的。
     *
     * [note]事务之间的调用不能在同一个类里面，可以通过调用栈来查看，因为事务是通过拦截bean来操作的，如果在同一个bean里面就不起作用
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void demoA() throws Exception {
        sb.demoB();
        Map<String, String> user = new HashMap<>();
        user.put("username", "高嘉银");
        user.put("password", "123456");
        bd.save("UserMapper.insertOneUser", user);
    }
}
